#ifndef PUZZLE_REGION_H_
#define PUZZLE_REGION_H_

// INCLUDES //
#include "region.h"
#include "queue_region.h"
#include "physics/puzzle_path.h"
//////////////

// CONSTANTS //
#define PUZZLE_BOARD_WIDTH		10
#define PUZZLE_BOARD_HEIGHT		18
#define PUZZLE_PATTERN_SIZE		6
///////////////

/**
* A region that represents the main puzzle area.
* 
* @see PuzzlePathListener
* @author dfoelber
**/
class PuzzleRegion : public Region, PuzzlePathListener
{
private:
	class PuzzleSelection
	{
	public:
		/// X coordinate
		int			x;
		/// Y coordinate
		int			y;
		/// Width
		int			width;
		/// Height
		int			height;
		/// If the possibility is selected
		bool		selected;
		/// If the possibility is hovered
		bool		hovered;
	};
	
public:
	/**
	* Constructor
	**/
	PuzzleRegion();
	
	/**
	* Destructor
	**/
	virtual ~PuzzleRegion();
	
	/**
	* Sets the queue region.
	* 
	* @param region The queue region
	**/
	void SetQueueRegion(QueueRegion* region) { queueRegion = region; }
	
	/**
	* Loads a pattern to match.
	* 
	* @param pattern The pattern to match
	**/
	void LoadPattern( char pattern[PUZZLE_PATTERN_SIZE][PUZZLE_PATTERN_SIZE] );
	
	/**
	* Unloads the current pattern, if any.
	**/
	void UnloadPattern();
	
	/**
	* Notify the region of an event.
	* 
	* Overridden from Region.
	* 
	* @param event The event that happened
	* @return If the region used the event
	**/
	virtual bool ProcessEvent( SDL_Event event );
	
	/**
	* Notifies of time passing.
	* 
	* Overridden from Region.
	* 
	* @param The amount of time, in milliseconds, that passed since the last call
	**/
	virtual void TimePassed( int ms );
	
	/**
	* Renders the objects on the background
	* 
	* Overridden from Region.
	**/
	virtual void Render();
	
	/**
	* Notifies region to start dropping pieces. Will be taken out later.
	**/
	void Start();
	
	/**
	* Invoked when the puzzle path has finished dropping.
	* 
	* Overridden from PuzzlePathListener.
	**/
	void PuzzlePathFinished();
	
	/**
	* Removes the given object from the region.
	* 
	* Overridden from Region.
	* 
	* @param object The object to remove
	* @param del If the object should be deleted
	**/
	virtual void RemoveObject(Object* object, bool del = true);
	
	/**
	* Clears all checked selections from the board.
	**/
	void ClearSelections();
	
	/**
	* Gets the number of active selections from the board.
	**/
	int GetNumberOfSelections() { return (int)selections.size(); }
	
	/**
	* Cancels the act of selection, leaving the gem pieces.
	**/
	void CancelSelection();
	
	/**
	* Sets a pattern to check for selections.
	**/
	void SetSelection(vector<vector<char> > pattern);
	
protected:
	/**
	* Calls for optional custom rendering.
	* 
	* Overridden from Region.
	* 
	* @returns If the region requires to flipped entirely (as opposed to flipping just the objects)
	**/
	virtual bool CustomRender();
	
private:
	/**
	* Adds a new gem piece to the region.
	**/
	void AddNewGem();
	
	/**
	* Checks if any object is not supported, changes to falling if not.
	**/
	void CheckForFalling();
	
	/**
	* Populates the selection list with pattern matches.
	**/
	void CheckPatterns();
	
private:
	/// Queue region, to get the next gems
	QueueRegion*				queueRegion;
	/// If the region is in the process of finishing.
	bool						finishing;
	/// If the region is adding a new gem.
	bool						adding;
	/// Semaphore for adding gems.
	SDL_sem*					semaphore;
	/// List of falling objects
	vector<Object*>				fallingObjects;
	/// The current pattern to match
	char						pattern[PUZZLE_PATTERN_SIZE][PUZZLE_PATTERN_SIZE];
	/// The current pattern's selection X offset
	int							patternXOffset;
	/// The current pattern's selection Y offset
	int							patternYOffset;
	/// The current pattern's selection width
	int							patternWidth;
	/// The current pattern's selection height
	int							patternHeight;
	/// If the region is in pattern matching mode
	bool						matchPattern;
		
	/// List of selection possibilities
	vector<PuzzleSelection*>	selections;
};

#endif /*PUZZLE_REGION_H_*/
